<template>
  <div>
    <el-switch v-model="draggable" active-text="开启拖拽" inactive-text="关闭拖拽">
    </el-switch>

    <el-button type="danger" @click="batchDelete" round>批量删除</el-button>
    <el-button icon="el-icon-refresh"  @click="clearChecked" circle></el-button>

    <!-- 
        draggable 可拖拽 
        default-expanded-keys 默认展开节点 
        show-checkbox 选择框  
        expand-on-click-node false为点击节点可以展开,true 要点击展开箭头
        allow-drop 判断是否允许拖拽 
        @node-drop 拖拽成功的回调事件  “v-on”指令的简写是“@”
        
        ref="menuTree"  作用,调用组件提供的方法
        this.$refs 得到所有组件
        this.$refs.menuTree 得到树的组件
        this.$refs.menuTree.getCheckedNodes  调用树组件的获取选中节点的方法
    -->
    <el-tree :data="menus" node-key="catId" show-checkbox :props="defaultProps" :default-expanded-keys="expandedKey"
      :allow-drop="allowDrop" @node-drop="handleDrop" :expand-on-click-node="false" :draggable="draggable"
      ref="menuTree">

      <!-- slot-scope="{ node, data }" 这里是传递两个参数,解构写法 -->
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <!-- 不是最后一个层级的时候新增 这里的node是上面 slot-scope 定义的 -->
          <el-button v-if="node.level <= 2" type="text" size="mini" @click="() => append(data)">
            新增
          </el-button>

          <el-button type="text" size="mini" @click="() => edit(data)">
            修改
          </el-button>

          <!-- 没有子节点时可以删除 -->
          <el-button v-if="node.childNodes.length == 0" type="text" size="mini" @click="() => remove(node, data)">
            删除
          </el-button>

        </span>
      </span>
    </el-tree>

    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="30%">
      <el-form :model="category">
        <el-form-item label="分类名称">
          <el-input v-model="category.name" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="图标">
          <el-input v-model="category.icon" autocomplete="off"></el-input>
        </el-form-item>

        <el-form-item label="计量单位">
          <el-input v-model="category.productUnit" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitData">确 定</el-button>
      </span>
    </el-dialog>

  </div>
</template>

<script>
export default {
  data() {
    return {
      category: {
        catId: null,
        name: "",
        parentCid: 0,
        catLevel: 0,
        productUnit:"",
        iconL:""
      }, //表单数据对象	
      draggable:false, //是否允许拖拽,true 
      maxLevel:1, //用来计算节点深度值
      dialogType: "", //新增打开 赋值 add, 修改打开 赋值 edit
      dialogVisible: false, //新增对话框
      dialogTitle:"", //新增或修改弹出框标题
      menus: [],  //树内容
      expandedKey: [164], //默认展开的节点
      defaultProps: {
        children: 'children', //配置子树是对象的那个属性
        label: 'name'  //对应树结构中的名字, 配置显示字段
      }
    };
  },
  components: {
  },
  methods: {
    getMenus() {
      this.$http({
        url: this.$http.adornUrl('/product/category/list/tree'),
        method: 'get',
      }).then(({ data }) => {
        //{data} 把数据中的data解构出来
        this.menus = data.data;
      })
    },
    edit(data) {
      this.dialogVisible = true;
      this.dialogType = "edit";
      this.dialogTitle = "修改分类";

      //获取当前节点最新数据
      this.$http({
        url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
        method: 'get',
      }).then(({ data }) => {
        //{data} 把数据中的data解构出来
        //this.category = data.data;

        //拓展运算符（...）用于取出参数对象所有可遍历属性然后拷贝到当前对象。
        this.category = {...data.data};
      })

    },
    append(data) {
      this.dialogVisible = true;
      this.dialogType = "add";
      this.dialogTitle = "新增分类";

      //重置数据,修改时绑定的数据重置
      // this.category.name = "";
      // this.category.catId = null;
      // this.category.icon = "";
      // this.category.productUnit = "";
      
      //初始化数据为默认值
      this.category = this.$options.data().category;

      this.category.parentCid = data.catId;//新增节点的父id
      this.category.catLevel = data.catLevel * 1 + 1; // * 1 的目的当level是字符串时自动转换
    },
    submitData() {
      if (this.dialogType == "add") {
        this.addCategory();
      }

      if (this.dialogType == "edit") {
        this.editCategory();
      }
    }
    ,
    //修改分类  
    editCategory() {
      console.log("表单分类数据： ", this.category);

      let {productUnit,icon,name,catId} = this.category; //属性从对象中解构出来 

      this.$http({
        url: this.$http.adornUrl('/product/category/update'),
        method: 'post',
        data: this.$http.adornData({productUnit,icon,name,catId} , false) //只发送要修改的属性
      }).then(({ data }) => {
        this.$message({
          message: '修改分类成功',
          type: 'success'
        });
        this.dialogVisible = false;
        this.getMenus();
        this.expandedKey = [this.category.parentCid];
      })

    },
    //添加分类  
    addCategory() {
      /*
        新增节点 (Dialog 对话框)
        - 添加名称 
        - 分类名,父节点id,层级
      */

      console.log("表单分类数据： ", this.category);
      this.$http({
        url: this.$http.adornUrl('/product/category/save'),
        method: 'post',
        data: this.$http.adornData(this.category, false)
      }).then(({ data }) => {
        this.$message({
          message: '新增分类成功',
          type: 'success'
        });
        this.dialogVisible = false;
        this.getMenus();
        this.expandedKey = [this.category.parentCid];
      })
    },
    remove(node, data) {
      /*
          删除功能 
          1. 删除前,进行弹窗确定(el-ui MessageBox 弹框)
          2. 删除后进行提示 (el-ui Message 消息提示)
          3. 删除后重新加载树结构,加载后树不收起
             实现: 获取删除父节点,进行展开 default-expanded-keys
      
      */
      this.$confirm(`是否删除[${data.name}]分类`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        let ids = [data.catId];
        this.$http({
          url: this.$http.adornUrl('/product/category/delete'),
          method: 'post',
          data: this.$http.adornData(ids, false)
        }).then(({ data }) => {
          this.$message({
            message: '分类删除成功',
            type: 'success'
          });
          this.getMenus();
          this.expandedKey = [node.parent.data.catId];
        })
      }).catch(() => {

      });
    },
    //allow-drop 判断是否允许拖拽 
    //draggingNode 当前节点 dropNode 要放的节点 type 要放的位置 'prev'、'inner' 和 'next'，分别表示放置在目标节点前
    allowDrop(draggingNode, dropNode, type) {
      this.maxLevel = 1;
      //拖动后总层级数不能大于三 
      this.countNodeLevel(draggingNode.data);

      //当前拖动节点的层数 
      let nodeDeep = this.maxLevel - draggingNode.data.catLevel + 1;

      if(type == "inner"){
        return nodeDeep + dropNode.level <= 3;
      }else{
        return nodeDeep + dropNode.parent.level <= 3;
      }
    },
    //统计节点最深节点的level 
    countNodeLevel(node){
      if (node.catLevel > this.maxLevel) {
        this.maxLevel = node.catLevel;
      }

      //找出所有子节点,得到最大深度
      if(node.children != null && node.children.length > 0){
        //有子节点就递归 
        for (let i = 0; i < node.children.length; i++) {
          if(node.children[i].catLevel > this.maxLevel){
            this.maxLevel = node.children[i].catLevel;
          }
          this.countNodeLevel(node.children[i]);
        }
      }
    },
    //共四个参数，依次为：被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置（before、after、inner）、event(事件对象)
    //拖拽完成回调事件   TODO(暂时不做) 
    handleDrop(draggingNode, dropNode, dropType, ev) {
      console.log('tree drop: ',draggingNode , dropNode, dropType);

      //当前节点新的父节点的Id 
      let pCid = 0;
      let sibling = null;
      //拖拽节点的所在顺序

      //拖拽节点新的层级

    },
    //批量删除
    batchDelete() {
      //说明见 ref="menuTree" 定义处
      //目前被选中的节点 getCheckedNodes(leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数
      //1. 是否只是叶子节点，默认值为 false 2. 是否包含半选节点，默认值为 false (子节点被选中,父节点没有被全选中就是半选)

      //let checkNodes = this.$refs.menuTree.getCheckedNodes(); //得到所有文件

      this.$confirm(`是否删除选中分类`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {

        let ids = this.$refs.menuTree.getCheckedKeys();
        console.log("被选中的元素: ", ids);

        this.$http({
          url: this.$http.adornUrl('/product/category/delete'),
          method: 'post',
          data: this.$http.adornData(ids, false)
        }).then(({ data }) => {
          this.$message({
            message: '分类删除成功',
            type: 'success'
          });
          this.getMenus();
          //this.expandedKey = [node.parent.data.catId];
        })
      }).catch(() => {

      });

    },
    //取消选中
    clearChecked() {
      this.$refs.menuTree.setCheckedKeys([]);
    }
  },
  //生命周期函数 在实例创建完成后被立即同步调用。 
  created() {
    this.getMenus();
  }
}
</script>

<style>
input[aria-hidden="true"] {
    display: none !important;
}

.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner {
    box-shadow: none;
}

</style>